/**
 * Author:   e20160504
 * Date:     2018/7/6 16:54
 * Description:
 */
package com.kevin.demo.aspect;

import com.kevin.demo.annotation.AbleInsertOrUpdateLog;
import com.kevin.demo.dao.log.TestLogDao;
import com.kevin.demo.entity.log.Log;
import com.kevin.demo.entity.log.TestLog;
import com.kevin.demo.enums.OprEnum;
import com.kevin.demo.parser.ContentParser;
import com.kevin.demo.utils.*;
import io.swagger.annotations.ApiModelProperty;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;

/*日历记录：根据数据参数ID判断库中是否有存在此记录，如果存在则为更新，记录更新日志
            如果不存在此记录，则为新增记录记录新增日志
  Dao,在注解里注入，实现动态日志dao
 */
@Aspect
@Component
public class LogAspect {

    private final static Logger logger = LoggerFactory.getLogger(LogAspect.class);

    private TestLog log = new TestLog();
    private Object oldObject;
    private Object newObject;

    private Long startTime;
    private Long time;
    //前端参数
    private Object info;

    @Autowired
    private TestLogDao dao;


    @Before("@annotation(ableLog)")
    public void doBefore(JoinPoint joinPoint, AbleInsertOrUpdateLog ableLog) throws Exception {

        logger.info("日志aspect do before 开始");

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        info = joinPoint.getArgs()[0];
        log.setUsername(ContextUtil.getName());
        log.setModifyip(SysUtil.getClientIp(request));

        try {
            ContentParser contentParser = (ContentParser) ableLog.parseclass().newInstance();
            oldObject = contentParser.getResult(info, ableLog);

        } catch (Exception e) {
            logger.error("service加载失败:", e);
            throw new Exception(e.getMessage());
        }

        logger.info("日志aspect do before 结束");

        startTime = System.currentTimeMillis();
        logger.info("方法开始：" + startTime);
    }

    @AfterReturning(pointcut = "@annotation(ableLog)", returning = "object")
    public void doAfterReturing(Object object, AbleInsertOrUpdateLog ableLog) {
        time = System.currentTimeMillis() - startTime;
        logger.info("方法用时：" + time);

        logger.info("日志aspect do after 开始");

        List<Map<String, Object>> changelist;

        ContentParser contentParser = null;
        try {
            contentParser = (ContentParser) ableLog.parseclass().newInstance();
        } catch (Exception e) {
        }

        String handeledName = ableLog.handledName();
        if (oldObject == null) {
            log.setModifyname(OprEnum.UPDATE);
            //log.setOldObject(oldObject.toString());
            log.setModifyobject(OprEnum.UPDATE + handeledName);
            try {
                newObject = contentParser.getResult(info, ableLog);
                log.setNewObject(newObject.toString());
            } catch (Exception e) {
                logger.error("service加载失败:", e);
            }
            try {
                //使用swagger的注解
                changelist = ReflectionUtil.compareTwoClass(oldObject, info, ApiModelProperty.class);
                StringBuilder str = new StringBuilder();
                for (Map<String, Object> map : changelist) {
                    str.append("【" + map.get("name") + "】从【" + map.get("old") + "】改为了【" + map.get("new") + "】\n");
                }
                log.setModifycontent(str.toString());
            } catch (Exception e) {
                logger.error("比较异常", e);
            }
        } else {

            log.setNewObject(info.toString());
            log.setModifyname(OprEnum.SAVE);
            log.setModifyobject(OprEnum.SAVE + handeledName);
        }

        if ((oldObject != null && !StrUtil.isEmpty(log.getModifycontent())) || oldObject == null) {
            dao.insert(log);
        }

        logger.info("日志aspect do after 结束");
    }
}














































